/*
 * Copyright (c) 2017,安徽皖通科技股份有限公司 All rights reserved.
 */

package com.wttech.dzzf.process.service.errordata;

import com.wtkj.vo.dzzf.base.kfwd.FundAccount;
import com.wttech.dzzf.process.constant.UserConstants;
import com.wttech.dzzf.process.dao.ErrorUserNameDao;
import com.wttech.dzzf.process.dao.TransferUserInfoDao;
import com.wttech.dzzf.process.model.FundTemp;
import com.wttech.dzzf.process.service.user.UserDetailInfosCreatorService;
import com.wttech.dzzf.process.util.BusinessUtils;
import com.wttech.sjhj.check.moduleSet.CheckUserUpload_8;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

/**
 * 收集用户名称无法通过验证的信息
 *
 * @author MaShibo
 * @date 2017/11/8.
 */
@Service
public class ErrorUserNameCollectService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ErrorUserNameCollectService.class);

    private static final Logger ERRORINFO = LoggerFactory.getLogger("ErrorInfo");

    private static final int DEFAULT_PROCESS_NUM = 10000;

    /**
     * 同步锁
     */
    private static final Object LOCK = new Object();

    /**
     * 校验字段-用户姓名
     */
    private static final String USERNAME_STR = "userName";

    /**
     * 校验字段-经办人姓名
     */
    private static final String AGENTNAME_STR = "agentName";

    @Resource
    private UserDetailInfosCreatorService userDetailInfosCreatorService;

    @Resource
    private ErrorUserNameDao errorUserNameDao;

    @Resource
    private TransferUserInfoDao transferUserInfoDao;

    @Resource
    private ThreadPoolTaskExecutor executor;

    /**
     * 待处理数据总数
     */
    private volatile int total;

    static {
        CheckUserUpload_8.userType = UserConstants.DEFAULT_COMPANY_USERTYPE;
    }


    private void analyseData() {
        total = errorUserNameDao.queryFundAccontNum();
        LOGGER.info("共{}条待处理的资金账户信息", total);
        int count = (int) Math.ceil((double) total / DEFAULT_PROCESS_NUM);
        LOGGER.info("共需要处理{}次", count);
        List<Future<Void>> futures = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            futures.add(executor.submit(new SubAnalyseThread(i + 1)));
        }
        userDetailInfosCreatorService.getFutureResult(futures);
        LOGGER.info("数据分析完成");
        executor.shutdown();
    }

    private class SubAnalyseThread implements Callable<Void> {

        private int count;

        SubAnalyseThread(int count) {
            this.count = count;
        }

        @Override
        public Void call() throws Exception {
            LOGGER.info("第{}次开始执行", count);
            int startRow = (count - 1) * DEFAULT_PROCESS_NUM + 1;
            int endRow = count * DEFAULT_PROCESS_NUM;
            List<FundAccount> fundAccounts = errorUserNameDao.queryFundAccountInfosByRow(startRow, endRow);
            fundAccounts.forEach(this::recodAnalysisResult);
            LOGGER.info("第{}次结束执行", count);
            return null;
        }

        /**
         * 记录分析结果
         *
         * @param fundAccount 资金账户信息
         */
        private void recodAnalysisResult(FundAccount fundAccount) {
            String userName = BusinessUtils.regularString(fundAccount.getFundAccountName());
            try {
                String result1 = CheckUserUpload_8.checkUserUpload(USERNAME_STR, userName);
                if (!StringUtils.equalsIgnoreCase(result1, UserConstants.RIGHT)) {
                    ERRORINFO.info("用户名称【{}】不符合校验规则，原因【{}】", userName, result1);
                    saveErrorRecord(fundAccount.getFundAccountId());
                } else {
                    FundAccount temp = new FundAccount();
                    temp.setFundAccountId(fundAccount.getFundAccountId());
                    temp.setFundAccountName(userName);
                    updateFundAccoutInfos(temp);
                }
            } catch (ParseException e) {
                LOGGER.error(e.getMessage(), e);
            }

            int ownerType = fundAccount.getOwnerType();
            String agentName = BusinessUtils.regularString(fundAccount.getRelationName());
            if (ownerType == UserConstants.OLD_OWNERTYPE_COMPANY && StringUtils.isNotBlank(agentName)) {
                try {
                    String result2 = CheckUserUpload_8.checkUserUpload(AGENTNAME_STR, agentName);
                    if (!StringUtils.equalsIgnoreCase(result2, UserConstants.RIGHT)) {
                        ERRORINFO.info("经办人姓名【{}】不符合校验规则，原因【{}】", agentName, result2);
                        saveErrorRecord(fundAccount.getFundAccountId());
                    } else {
                        FundAccount temp = new FundAccount();
                        temp.setFundAccountId(fundAccount.getFundAccountId());
                        temp.setRelationName(agentName);
                        updateFundAccoutInfos(temp);
                    }
                } catch (ParseException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }

            synchronized (LOCK) {
                LOGGER.info("还有【{}】条数据待处理", --total);
            }
        }

        /**
         * 报错错误的记录
         *
         * @param fundAccountId 资金账户ID
         */
        private void saveErrorRecord(String fundAccountId) {
            FundTemp temp = new FundTemp();
            temp.setFundAccountId(fundAccountId);
            try {
                transferUserInfoDao.createTestObjcet(temp);
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
                LOGGER.info("错误的记录【{}】", temp);
            }
        }

        /**
         * 更新资金账户信息
         *
         * @param fundAccount 待更新的资金账户信息
         */
        private void updateFundAccoutInfos(FundAccount fundAccount) {
            try {
                transferUserInfoDao.updateTestObject(fundAccount);
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
                LOGGER.info("错误的记录【{}】", fundAccount);
            }
        }
    }

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        ErrorUserNameCollectService service = context.getBean(ErrorUserNameCollectService.class);
        service.analyseData();
    }
}
